import { Injectable } from "@nestjs/common";

import { PrismaService } from "@/core/db/prisma.service";
import BusinessException from "@/core/exception/BusinessException";
import { buildTree } from "@/core/utils/treeUtils";
import { PageResultVO } from "@/core/vo/page-result.vo";

import { CreateFileDirDto } from "../dto/create-file-dir.dto";
import { QueryFileDirDto } from "../dto/query-file-dir.dto";
import { UpdateFileDirDto } from "../dto/update-file-dir.dto";

@Injectable()
export class FileDirService {
    constructor(private readonly prismaService: PrismaService) {}

    async create(createFileDirDto: CreateFileDirDto) {
        const fileDir = await this.prismaService.fileDirectory.findFirst({
            where: {
                name: createFileDirDto.name,
                isDeleted: false
            }
        });

        if (fileDir) throw new BusinessException("DATA_EXISTS");

        return await this.prismaService.fileDirectory.create({
            data: createFileDirDto
        });
    }

    async findListPage(query: QueryFileDirDto) {
        const { current, size, name, type } = query;
        const [listData, total] = await Promise.all([
            this.prismaService.fileDirectory.findMany({
                where: {
                    name: {
                        contains: name
                    },
                    type,
                    isDeleted: false
                },
                skip: (current - 1) * size,
                take: size,
                orderBy: {
                    sort: "asc"
                }
            }),
            this.prismaService.fileDirectory.count({
                where: {
                    name: {
                        contains: name
                    },
                    type,
                    isDeleted: false
                }
            })
        ]);

        const pages = Math.ceil(total / size);
        return new PageResultVO(listData, total, pages, current, size);
    }

    async findAll() {
        return await this.prismaService.fileDirectory.findMany({
            where: {
                isDeleted: false
            }
        });
    }

    async getTreeFileDir(query: QueryFileDirDto) {
        const { name, type } = query;
        const fileDirs = await this.prismaService.fileDirectory.findMany({
            where: {
                name: {
                    contains: name
                },
                type,
                isDeleted: false
            },
            orderBy: {
                sort: "asc"
            }
        });

        return buildTree(fileDirs);
    }

    async findOne(id: number) {
        return await this.prismaService.fileDirectory.findUnique({
            where: {
                id,
                isDeleted: false
            }
            // include: {
            //     UploadFile: {
            //         skip: 0,
            //         take: 15,
            //         orderBy: {
            //             createdAt: "asc"
            //         },
            //         where: {
            //             isDeleted: false
            //         }
            //     }
            // }
        });
    }

    async update(id: number, updateFileDirDto: UpdateFileDirDto) {
        let fileDir;
        try {
            fileDir = await this.prismaService.fileDirectory.update({
                where: {
                    id,
                    isDeleted: false
                },
                data: updateFileDirDto
            });
        } catch (error) {
            throw new BusinessException("DATA_NOT_FOUND");
        }
        return fileDir;
    }

    async remove(id: number, softDelete: boolean = true) {
        try {
            if (softDelete) {
                await this.prismaService.fileDirectory.update({
                    where: {
                        id,
                        isDeleted: false
                    },
                    data: {
                        isDeleted: true,
                        deletedAt: new Date()
                    }
                });
            } else {
                await this.prismaService.fileDirectory.delete({
                    where: {
                        id,
                        isDeleted: false
                    }
                });
            }
        } catch (error) {
            throw new BusinessException();
        }
    }
}
